const puppeteerExtra = require('puppeteer-extra');
const puppeteerExtraPluginStealth = require('puppeteer-extra-plugin-stealth');
const fs = require('fs/promises');
const path = require('path');
const config = require('./config');
const proxyFetcher = require('./scraper');

// 获取当前系统的 Chrome 路径
const getChromePath = () => config.CHROME_PATH[process.platform];

// 启用 stealth 插件
puppeteerExtra.use(puppeteerExtraPluginStealth());

// 修改获取随机代理的函数
async function getRandomProxy() {
    if (!config.PROXY_CONFIG.enabled) return null;
    return await proxyFetcher.getProxy();
}

// 修改浏览器启动配置
async function launchBrowserWithProxy() {
    const args = [...config.BROWSER_CONFIG.args];

    if (config.PROXY_CONFIG.enabled) {
        const proxy = await getRandomProxy();
        if (proxy) {
            try {
                const [host, port] = proxy.split('://')[1].split(':');
                args.push(`--proxy-server=http://${host}:${port}`);
                console.log(`使用代理: ${host}:${port}`);
            } catch (error) {
                console.error('代理设置失败:', error.message);
            }
        }
    }

    return await puppeteerExtra.launch({
        ...config.BROWSER_CONFIG,
        executablePath: getChromePath(),
        args,
        ignoreHTTPSErrors: true
    });
}

// 修改页面设置函数
async function setupPage(page) {
    await page.setRequestInterception(true);

    page.on('request', async request => {
        try {
            const headers = {
                ...request.headers(),
                'Referer': 'http://www.netbian.com/'
            };

            request.continue({
                headers
            });
        } catch (error) {
            request.continue();
        }
    });
}

async function scrapeWallpapers(startPage = 1, endPage = 3) {
    try {
        const allWallpapers = [];
        const browser = await launchBrowserWithProxy();
        const page = await browser.newPage();
        await setupPage(page);

        for (let currentPage = startPage; currentPage <= endPage; currentPage++) {
            try {
                let sum = 0;
                const pageUrl = currentPage === 1 ?
                    config.BASE_URL :
                    `${config.BASE_URL}index_${currentPage}.htm`;

                console.log(`\n正在抓取第 ${currentPage} 页...`);


                // 获取当前页的壁纸列表
                const getPageWallpapers = async (page) => {
                    await page.goto(pageUrl, {
                        waitUntil: 'networkidle0',
                        timeout: config.TIMEOUT
                    });
                    let pageWallpapers = await page.evaluate(() => {
                        const items = document.querySelectorAll('.list a');
                        return Array.from(items).map(item => ({
                            title: item.title || '未命名',
                            href: item.href
                        }));
                    });
                    pageWallpapers = pageWallpapers.filter(item => item.title !== '未命名');
                    return pageWallpapers;

                }
                // 获取当前页的壁纸列表

                pageWallpapers = await getPageWallpapers(page)
                while (pageWallpapers.length === 0 && sum <= 3) {
                    sum++;
                    pageWallpapers = await getPageWallpapers(page)
                    pageWallpapers = pageWallpapers.concat(pageWallpaper);
                    pageWallpaper.length ? sum = 4 : sum++;
                }

                allWallpapers.push(...pageWallpapers);
                console.log(`第 ${currentPage} 页过滤未命名后获取到 ${pageWallpapers.length} 张图片`);

                // 添加页面间隔，避免请求过快
                if (currentPage < endPage) {
                    const delay = 3000 + Math.random() * 2000;
                    console.log(`等待 ${Math.round(delay/1000)} 秒后继续下一页...`);
                    await new Promise(resolve => setTimeout(resolve, delay));
                }
            } catch (error) {
                console.error(`抓取第 ${currentPage} 页时出错:`, error.message);
                continue; // 继续下一页
            }
        }

        await browser.close();
        console.log(`总共获取到 ${allWallpapers.length} 张图片`);
        return allWallpapers;

    } catch (error) {
        console.error('发生错误：', error);
        throw error;
    }
}

async function getImages(wallpapers) {
    const downloadPath = path.resolve(config.DOWNLOAD_PATH);
    await fs.mkdir(downloadPath, {
        recursive: true
    });

    const browser = await launchBrowserWithProxy();

    try {
        // 第一轮：正常下载
        console.log('开始正常下载流程...');
        const errorWallpapers = []

        const firstRoundFailures = await downloadWithConcurrency(
            wallpapers,
            config.MAX_CONCURRENT,
            false,
            browser
        );

        if (firstRoundFailures.length > 0) {
            console.log(`\n第一轮有 ${firstRoundFailures.length} 个项目下载失败，开始第二轮重试...`);

            // 第二轮：较低并发，更长超时
            const secondRoundFailures = await downloadWithConcurrency(
                firstRoundFailures,
                Math.min(firstRoundFailures.length, 5),
                1,
                browser
            );

            if (secondRoundFailures.length > 0) {
                console.log(`\n第二轮仍有 ${secondRoundFailures.length} 个项目失败，开始第三轮重试...`);

                // 第三轮：更低并发，更长超时
                const thirdRoundFailures = await downloadWithConcurrency(
                    secondRoundFailures,
                    Math.min(secondRoundFailures.length, 3),
                    2,
                    browser
                );

                if (thirdRoundFailures.length > 0) {
                    console.log(`\n第三轮仍有 ${thirdRoundFailures.length} 个项目失败，开始第四轮重试...`);

                    // 第四轮：单个下载，超长超时
                    const fourthRoundFailures = await downloadWithConcurrency(
                        thirdRoundFailures,
                        1, // 一次只下载一个
                        3, // 第四轮，更长的超时时间
                        browser
                    );

                    if (fourthRoundFailures.length > 0) {
                        console.log(`\n第四轮仍有 ${fourthRoundFailures.length} 个项目失败，最后一次尝试...`);

                        // 第五轮：最后的尝试，单个下载，最长超时
                        const finalFailures = await downloadWithConcurrency(
                            fourthRoundFailures,
                            1, // 一次只下载一个
                            4, // 第五轮，最长的超时时间
                            browser
                        );

                        // 输出最终失败的项目，并保存到文件
                        if (finalFailures.length > 0) {
                            console.log('\n以下项目最终下载失败：');
                            const failureLog = finalFailures.map(item => ({
                                title: item.title,
                                originalIndex: item.originalIndex + 1,
                                error: item.error,
                                href: item.href,
                                timestamp: new Date().toISOString()
                            }));

                            // 保存失败记录到文件
                            const logPath = path.join(downloadPath, 'failed_downloads.json');
                            await fs.writeFile(
                                logPath,
                                JSON.stringify(failureLog, null, 2)
                            );

                            console.log('\n失败记录已保存到:', logPath);
                            finalFailures.forEach(item => {
                                console.log(`\n- ${item.title} (原始索引: ${item.originalIndex + 1})`);
                                console.log(`  错误信息: ${item.error}`);
                                console.log(`  链接: ${item.href}`);
                            });
                        }
                    }
                }
            }
        }
    } finally {
        await browser.close();
    }
}

// 修改并发下载函数，添加 downloadPath 参数
async function downloadWithConcurrency(tasks, maxConcurrent, isRetry = false, browser) {
    const executing = new Set();
    const currentFailures = []; // 当前批次的失败项
    const downloadPath = path.resolve(config.DOWNLOAD_PATH);

    // 修改超时时间设置
    const getTimeoutByRetry = (isRetry) => {
        switch (isRetry) {
            case false:
                return 60000; // 第一轮：60秒
            case 1:
                return 90000; // 第二轮：90秒
            case 2:
                return 120000; // 第三轮：120秒
            case 3:
                return 180000; // 第四轮：180秒
            case 4:
                return 300000; // 第五轮：300秒
            default:
                return 60000;
        }
    };

    for (const [index, wallpaper] of tasks.entries()) {
        const promise = (async () => {
            let page;
            try {
                page = await browser.newPage();
                await setupPage(page);

                // 设置当前轮次的超时时间
                const currentTimeout = getTimeoutByRetry(isRetry);
                await page.setDefaultNavigationTimeout(currentTimeout);

                // 增加重试时的延时
                const delay = isRetry ? 2000 + Math.random() * 3000 : 500 + Math.random() * 1500;
                await new Promise(resolve => setTimeout(resolve, delay));

                // 添加页面加载重试机制
                let retryCount = 0;
                let success = false;

                while (!success && retryCount < 3) {
                    try {
                        await page.goto(wallpaper.href, {
                            waitUntil: 'networkidle0',
                            timeout: currentTimeout
                        });
                        success = true;
                    } catch (error) {
                        retryCount++;
                        console.log(`加载页面失败，第 ${retryCount} 次重试...`);

                    }
                }

                if (!success) {
                    throw new Error('页面加载失败，已达到最大重试次数');
                }

                // 等待图片元素出现
                await page.waitForSelector('.pic img', {
                    timeout: currentTimeout
                });

                const imgUrl = await page.evaluate(() => {
                    const img = document.querySelector('.pic img');
                    return img ? img.src : null;
                });

                if (imgUrl) {
                    const safeTitle = wallpaper.title.replace(/[\\/:*?"<>|]/g, '_');
                    const originalIndex = wallpaper.originalIndex !== undefined ? wallpaper.originalIndex : index;
                    const filename = `${originalIndex + 1}_${safeTitle}.jpg`;
                    const filepath = path.join(downloadPath, filename);

                    console.log(`下载中: ${filename}`);
                    console.log(`图片URL: ${imgUrl}`);

                    // 下载图片重试机制
                    retryCount = 0;
                    success = false;

                    while (!success && retryCount < 3) {
                        try {
                            const response = await page.goto(imgUrl, {
                                waitUntil: 'networkidle0',
                                timeout: currentTimeout
                            });

                            if (!response.ok()) {
                                throw new Error(`HTTP error! status: ${response.status()}`);
                            }

                            const buffer = await response.buffer();
                            await fs.writeFile(filepath, buffer);
                            console.log(`完成: ${filename}`);
                            success = true;
                        } catch (error) {
                            retryCount++;
                            console.log(`下载图片失败，第 ${retryCount} 次重试...`);
                            await new Promise(resolve => setTimeout(resolve, 2000));
                        }
                    }

                    if (!success) {
                        throw new Error('图片下载失败，已达到最大重试次数');
                    }
                } else {
                    throw new Error('未找到图片URL');
                }
            } catch (error) {
                console.error(`下载失败: ${wallpaper.title}`, error.message);
                currentFailures.push({
                    ...wallpaper,
                    originalIndex: wallpaper.originalIndex !== undefined ? wallpaper.originalIndex : index,
                    error: error.message
                });
            } finally {
                if (page) await page.close();
            }
        })();

        executing.add(promise);
        promise.then(() => executing.delete(promise));

        if (executing.size >= maxConcurrent) {
            await Promise.race(executing);
        }
    }

    await Promise.all(executing);
    return currentFailures;
}

// 修改 init 函数，支持页码参数
async function init(startPage = 1, endPage = 3) {
    console.log(`开始抓取第 ${startPage} 页到第 ${endPage} 页的图片...`);
    const data = await scrapeWallpapers(startPage, endPage);
    await getImages(data);
    // console.log(data)
}

// 启动程序，可以指定起始和结束页码
init(1, 10); // 抓取第1页到第3页